#include "Common.hpp"
#include "ConcurrentAlloc.hpp"
#include <vector>

size_t pageCount = 0;

void AllocAndFree1()
{
    std::vector<void*> arr;
    for (int i = 0; i < 7; ++i)
    {
        int *pi = (int *)ConcurrentAlloc(6); //对齐到8
        *pi = 12;
        arr.push_back(pi);
    }
    for (int i = 0; i < 7; ++i)
    {
        ConcurrentFree(arr[i]);
    }
}

void AllocAndFree2()
{
    std::vector<void*> arr;
    for (int i = 0; i < 7; ++i)
    {
        int *pi = (int *)ConcurrentAlloc(10); //对齐到16
        *pi = 12;
        arr.push_back(pi);
    }
    for (int i = 0; i < 7; ++i)
    {
        ConcurrentFree(arr[i]);
    }
}

// 验证TLS：看两个线程的ThreadCache地址是否不同
void Test_TLS()
{
    std::thread thread1(AllocAndFree1);
    std::thread thread2(AllocAndFree2);
    thread1.join();
    thread2.join();
}

// 一般测试：看内存池是否可以正常工作
void Test_ConcurrentAlloc1()
{
    int *p1 = (int *)ConcurrentAlloc(200); //maxsize:2 allocnum:1 size:0
    int *p2 = (int *)ConcurrentAlloc(200); //3 2 1
    int *p3 = (int *)ConcurrentAlloc(200); //3   0
    int *p4 = (int *)ConcurrentAlloc(200); //4 3 2
    int *p5 = (int *)ConcurrentAlloc(200); //4   1
    int *p6 = (int *)ConcurrentAlloc(200); //4   0
    int *p7 = (int *)ConcurrentAlloc(200); //5 4 3


    *p1 = 10;
    *p2 = 20;
    *p3 = 30;
    *p4 = 40;

    cout << p1 << ": " << *p1 << endl;
    cout << p2 << ": " << *p2 << endl;
    cout << p3 << ": " << *p3 << endl;
    cout << p4 << ": " << *p4 << endl;

    ConcurrentFree(p1); //maxsize:5 size:4 span._usecount:10
    ConcurrentFree(p2); //5 0 5 **
    ConcurrentFree(p3); //5 1 5
    ConcurrentFree(p4); //5 2 5
    ConcurrentFree(p5); //5 3 5
    ConcurrentFree(p6); //5 4 5
    ConcurrentFree(p7); //5 0 0 **
}

// 特殊测试：看CentralCache中的一页内存(4KB)分配完后，是否能正常从PageCache中分裂其他页
void Test_ConcurrentAlloc2()
{
    std::vector<double*> arr;
    for (int i = 0; i < 512; ++i)
    {
        double *pd = (double *)ConcurrentAlloc(8);
        arr.push_back(pd);
        *pd = 8.16;
        
    }
    cout << "Last ConcurrentAlloc!" << endl;
    double *pd = (double *)ConcurrentAlloc(8);
    arr.push_back(pd);
    *pd = 8.16;

    for(auto e : arr)
    {
        ConcurrentFree(e);
    }

    std::this_thread::sleep_for(std::chrono::seconds(5));
}

void Test_BigAlloc()
{
    int *p1 = (int *)ConcurrentAlloc(MAX_BYTES + 100);
    int *p2 = (int *)ConcurrentAlloc(NPAGES << PAGE_SHIFT);

    *p1 = 10;
    *p2 = 20;

    cout << p1 << ": " << *p1 << endl;
    cout << p2 << ": " << *p2 << endl;

    ConcurrentFree(p1);
    ConcurrentFree(p2);
}

void DefineStatic()
{
    static int cnt = 0;
    ++cnt;
    cout << &cnt << ": " << cnt << endl;
}

//复杂测试：多创建几个线程玩玩
void Test_ConcurrentAlloc3()
{
    std::vector<std::thread> threads(8);
    for(int i = 0; i < 8; ++i)
    {
        threads[i] = std::thread(AllocAndFree1); //只允许移动赋值
    }
    for(int i = 0; i < 8; ++i)
    {
        threads[i].join();
    }
}

// 一般测试：看内存池是否可以正常工作
void Test_ThreadDestroy()
{
    
    int *p1 = (int *)ConcurrentAlloc(6); //maxsize:2 allocnum:1 size:0
    int *p2 = (int *)ConcurrentAlloc(6); //3 2 1
    int *p3 = (int *)ConcurrentAlloc(6); //3   0
    int *p4 = (int *)ConcurrentAlloc(6); //4 3 2
    int *p5 = (int *)ConcurrentAlloc(6); //4   1
    int *p6 = (int *)ConcurrentAlloc(6); //4   0
    int *p7 = (int *)ConcurrentAlloc(6); //5 4 3
    int *p8 = (int *)ConcurrentAlloc(6); //5  2
    int *p9 = (int *)ConcurrentAlloc(6); //5  1
    int *p10 = (int *)ConcurrentAlloc(6); //5  0
    int *p11 = (int *)ConcurrentAlloc(6); //5 5 4



    *p1 = 10;
    *p2 = 20;
    *p3 = 30;
    *p4 = 40;

    cout << p1 << ": " << *p1 << endl;
    cout << p2 << ": " << *p2 << endl;
    cout << p3 << ": " << *p3 << endl;
    cout << p4 << ": " << *p4 << endl;

    ConcurrentFree(p1); //maxsize:6 size:5 span._usecount:15
    ConcurrentFree(p2); //6 0 9 **
    ConcurrentFree(p3); //6 1 9
    ConcurrentFree(p4); //6 2 9
    ConcurrentFree(p5); //6 3 9
    ConcurrentFree(p6); //6 4 9
    ConcurrentFree(p7); //6 5 9 **
    ConcurrentFree(p8); //6 0 3 **
    ConcurrentFree(p9); //6 0 0 **
    ConcurrentFree(p10); //6 0 0 **
    ConcurrentFree(p11); //6 0 0 **
}


int main()
{
    // std::thread td(Test_ThreadDestroy);
    // td.join();
    // std::this_thread::sleep_for(std::chrono::seconds(5));
    // Test_TLS();
    Test_ConcurrentAlloc2();
    return 0;
}